<!DOCTYPE html>
<html lang="zh-CH" >
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="author" content="" />
	
	
	
	<title>基于HeadFirst设计模式之工厂模式 ｜ zansimple</title>
	
    
    
    <meta name="description" content="定义简单工厂 简单工厂其实不是一种设计模式，比较像一种编程习惯。但由于经常被使用，所以给它一个“ Head First Patter 荣誉奖”。有些开发人员的确是把这个编程习惯误认为是“工厂模式” ,下次跟开发的朋友聊天无话可说的时候，这个应该是打破沉默的一个不错的选择。
不要因为简单工厂不是一个“真正的设计模式” ， 就忽略的它的用法。
我们先看一下披萨店例子的类图：
这就是简单工厂，下面要说的就是两个重量级的模式，它们都是工厂。
这里提醒一下： 在设计模式中，所谓的“实现一个接口”并“不一定”表示“写一个类” ，并继承这个接口。“实现一个接口”泛指“实现某个超类型（可以是类或者接口）的某个方法”工厂方法模式 所有工厂模式都用来封装对象的创建。工厂方法模式通过让子类决定该创建的对象是什么，来达到将兑现该创建的过程封装的目的。下面我们看一组类图来了解一下有哪些组成元素
  创建者( Creator ) 类
  产品类
  我们已经看到，将一个 orderPizza() 方法和一个工厂方法联合起来，就可以成为一个框架。除此之外，工厂方法将生产只是封装进各个创建者，这样的做法，也可以被视为一个框架。
定义工厂方法模式 工厂方法模式：定义了一个创建对象的接口，但由于子类决定要实例化的类的哪个，工厂方法让类把实例化推迟到子类。
工厂方法模式能够封装具体类型的实例化。看下面的类图，抽象的 Creator 提供了一个创建对象的方法的接口，也成为”工厂方法“。在抽象的 Creator 中，任何其他实现的方法，都可能使用到这个工厂方法所制造出来的产品，但只有子类真正实现这个工厂方法并创建产品。
对象依赖 当你实例化一个对象时，就是在依赖它的具体类。
依赖倒置原则 设计原则：
要依赖抽象，不要依赖具体类意思就是：不能让高层组件依赖底层组件，而且，不管高层或底层组件，“两者”都应该依赖于抽象。
所以在应用工厂方法之后，类图看起来就像这样：
高层组件（也就是 PizzaStore ）和底层组件（也就是这些比萨）都依赖了 Pizza 抽象。想要遵循依赖倒置原则，工厂方法并非是唯一的技巧，但却是最有威力的技巧之一。
抽象工厂模式 抽线工厂模式：提供一个接口，用于创建相关或依赖对象的家族，而不需要明确指定具体类。
抽象工厂允许客户使用抽象的接口来创建一组相关的产品，而不需要知道实际产出的具体的产品是什么。这样客户就从具体的产品中被解耦。我们看一下下面的类图了解一下其中的关系。
我们再从 PizzaStore 的观点看下面这张相当复杂的类图：
这里细心的朋友已经观察到了，抽象工厂的每个方法实际上看起来都像是工厂方法（例如；createDough() , createSource() 等）。每个方法都被声明成抽象，而子类的方法覆盖这些方法来创建某些对象。这不正是工厂方法吗？是的，抽象工厂的方法经常以工厂方法的方式实现，抽象工厂的任务是定义一个负责创建一组产品的接口。这个接口内的每个方法都负责创建一个具体产品，同时我们利用实现抽象工厂的子类来提供这些具体的做法。所以，在抽象工厂中利用工厂方法实现生产方法是相当自然的做法。
代码示例（比萨店）   创建原料工厂
 public interface PizzaIngredientFactory(){public Dough CreateDoough();public Sauce CreateSauce();public Clam CreateClam();." />
    

    

	
    
    <link rel="shortcut icon" href="https://lenzan.github.io/images/favicon.ico" />

    <link rel="stylesheet" type="text/css" media="screen" href="https://lenzan.github.io/css/normalize.css" />
    <link rel="stylesheet" type="text/css" media="screen" href="https://cdn.jsdelivr.net/npm/animate.css@4.1.0/animate.min.css" />
    <link rel="stylesheet" type="text/css" media="screen" href="https://lenzan.github.io/css/zozo.css" />
	<link rel="stylesheet" type="text/css" media="screen" href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css" />
    <link rel="stylesheet" type="text/css" media="screen" href="https://lenzan.github.io/css/highlight.css" />

    
    
</head>

<body>
    <div class="main animate__animated animate__fadeInDown">
        <div class="nav_container animated fadeInDown">
    <div class="site_nav" id="site_nav">
        <ul>
            
            <li>
                <a href="/">首页</a>
            </li>
            
            <li>
                <a href="/">unity</a>
            </li>
            
            <li>
                <a href="/">归档</a>
            </li>
            
            <li>
                <a href="/">关于</a>
            </li>
            
        </ul>
    </div>
    <div class="menu_icon">
        <a id="menu_icon"><i class="ri-menu-line"></i></a>
    </div>
</div>
        <div class="header animated fadeInDown">
    <div class="site_title_container">
        <div class="site_title">
            <h1>
                <a href="https://lenzan.github.io/">
                    <span>zansimple</span>
                    <img src="https://lenzan.github.io/images/logo.svg" />
                </a>
            </h1>
        </div>
        <div class="description">
            <p class="sub_title">专注于Unity虚拟现实开发，游戏开发</p>
            <div class="my_socials">
                
                <a href="https://lenzan.github.io/index.xml" type="application/rss+xml" title="rss" target="_blank"><i
                        class="ri-rss-fill"></i></a>
            </div>
        </div>
    </div>
</div>
        <div class="content">
            <div class="post_page">
                <div class="post animate__animated animate__fadeInDown">
                    <div class="post_title post_detail_title">
                        <h2><a href='/posts/design/headfirst-factory/'>基于HeadFirst设计模式之工厂模式</a></h2>
                        <span class="date">2018.07.16</span>
                    </div>
                    <div class="post_content markdown"><!-- raw HTML omitted -->
<h2 id="定义简单工厂">定义简单工厂</h2>
<p>简单工厂其实不是一种设计模式，比较像一种编程习惯。但由于经常被使用，所以给它一个“ Head First Patter 荣誉奖”。有些开发人员的确是把这个编程习惯误认为是“工厂模式” ,下次跟开发的朋友聊天无话可说的时候，这个应该是打破沉默的一个不错的选择。</p>
<p>不要因为简单工厂不是一个“真正的设计模式” ， 就忽略的它的用法。</p>
<p>我们先看一下披萨店例子的类图：</p>
<p><img src="/img/factory/factory.png" alt="factory"></p>
<p>这就是简单工厂，下面要说的就是两个重量级的模式，它们都是工厂。</p>
<p>这里提醒一下： <br>
<!-- raw HTML omitted -->在设计模式中，所谓的“实现一个接口”并“不一定”表示“写一个类” ，并继承这个接口。“实现一个接口”泛指“实现某个超类型（可以是类或者接口）的某个方法”<!-- raw HTML omitted --></p>
<h2 id="工厂方法模式">工厂方法模式</h2>
<p>所有工厂模式都用来封装对象的创建。工厂方法模式通过让子类决定该创建的对象是什么，来达到将兑现该创建的过程封装的目的。下面我们看一组类图来了解一下有哪些组成元素</p>
<ul>
<li>
<p>创建者( Creator ) 类<br>
<img src="/img/factory/factory2.png" alt="factory2"></p>
</li>
<li>
<p>产品类<br>
<img src="/img/factory/factory3.png" alt="factory3"></p>
</li>
</ul>
<p>我们已经看到，将一个 orderPizza() 方法和一个工厂方法联合起来，就可以成为一个框架。除此之外，工厂方法将生产只是封装进各个创建者，这样的做法，也可以被视为一个框架。</p>
<p><img src="/img/factory/factory4.png" alt="factory4"></p>
<h3 id="定义工厂方法模式">定义工厂方法模式</h3>
<p>工厂方法模式：定义了一个创建对象的接口，但由于子类决定要实例化的类的哪个，工厂方法让类把实例化推迟到子类。</p>
<p>工厂方法模式能够封装具体类型的实例化。看下面的类图，抽象的 Creator 提供了一个创建对象的方法的接口，也成为”工厂方法“。在抽象的 Creator 中，任何其他实现的方法，都可能使用到这个工厂方法所制造出来的产品，但只有子类真正实现这个工厂方法并创建产品。</p>
<p><img src="/img/factory/factory5.png" alt="factory5"></p>
<h2 id="对象依赖">对象依赖</h2>
<p>当你实例化一个对象时，就是在依赖它的具体类。</p>
<p><img src="/img/factory/factory6.png" alt="factory6"></p>
<h3 id="依赖倒置原则">依赖倒置原则</h3>
<p>设计原则：<br>
<!-- raw HTML omitted -->要依赖抽象，不要依赖具体类<!-- raw HTML omitted --><br>
意思就是：不能让高层组件依赖底层组件，而且，不管高层或底层组件，“两者”都应该依赖于抽象。</p>
<p>所以在应用工厂方法之后，类图看起来就像这样：<br>
<img src="/img/factory/factory7.png" alt="factory7"></p>
<p>高层组件（也就是 PizzaStore ）和底层组件（也就是这些比萨）都依赖了 Pizza 抽象。想要遵循依赖倒置原则，工厂方法并非是唯一的技巧，但却是最有威力的技巧之一。</p>
<h2 id="抽象工厂模式">抽象工厂模式</h2>
<p>抽线工厂模式：提供一个接口，用于创建相关或依赖对象的家族，而不需要明确指定具体类。</p>
<p>抽象工厂允许客户使用抽象的接口来创建一组相关的产品，而不需要知道实际产出的具体的产品是什么。这样客户就从具体的产品中被解耦。我们看一下下面的类图了解一下其中的关系。</p>
<p><img src="/img/factory/factory8.png" alt="factory8"></p>
<p>我们再从 PizzaStore 的观点看下面这张相当复杂的类图：</p>
<p><img src="/img/factory/factory9.png" alt="factory9"></p>
<p>这里细心的朋友已经观察到了，抽象工厂的每个方法实际上看起来都像是工厂方法（例如；createDough() , createSource() 等）。每个方法都被声明成抽象，而子类的方法覆盖这些方法来创建某些对象。这不正是工厂方法吗？是的，抽象工厂的方法经常以工厂方法的方式实现，抽象工厂的任务是定义一个负责创建一组产品的接口。这个接口内的每个方法都负责创建一个具体产品，同时我们利用实现抽象工厂的子类来提供这些具体的做法。所以，在抽象工厂中利用工厂方法实现生产方法是相当自然的做法。</p>
<h3 id="代码示例比萨店">代码示例（比萨店）</h3>
<ul>
<li>
<p>创建原料工厂</p>
<pre><code>  public interface PizzaIngredientFactory()
  {
      public Dough CreateDoough();
      public Sauce CreateSauce();
      public Clam CreateClam();
      ...
  }
</code></pre>
</li>
<li>
<p>创建纽约原料工厂</p>
<pre><code>  public class NYPizzaIngredientFactory : PizzaIngredientFactory{
      public Dough createDough(){
          return new ThinCrustDough();
      }

      public Dough createSauce(){
          return new MarinaraSauce();
      }

       public Clam createClam(){
          return new FreshClams();
      }
  }
</code></pre>
</li>
<li>
<p>比萨抽象类</p>
<pre><code>  public abstract class Pizza
  {
      string name;
      Dough dough;
      Sauce sauce;

      abstract void prepare();

      void Bake(){
          print(&quot;bake...&quot;);
      }

      void cut(){
          print(&quot;cut&quot;);
      }

      void Box()
      {
          print(&quot;box&quot;);
      }

      void SetName(string name){
          this.name = name;
      }

      string GetName(){
          return name;
      }

  }
</code></pre>
</li>
<li>
<p>CheesePizza 类</p>
<pre><code>  public class CheesePizza : Pizza{
      PizzaIngredientFactory ingredientFactory;
      public CheesePizza(PizzaIngredientFactory ingredientFactory){
          this.ingredientFactory = ingredientFactory;
      }

      void prepare(){
          print(&quot;prepare&quot; + name)
          dough = ingredientFactory.CreateDough();
          sauce = ingredientFactory.CreateSauce();
      }
  }
</code></pre>
</li>
<li>
<p>ClamPizza 类</p>
<pre><code>  public class ClamPizza : Pizza{
      PizzaIngredientFactory ingredientFactory;
      public CheesePizza(PizzaIngredientFactory ingredientFactory){
          this.ingredientFactory = ingredientFactory;
      }

      void prepare(){
          print(&quot;prepare&quot; + name)
          dough = ingredientFactory.CreateDough();
          sauce = ingredientFactory.CreateSauce();
          clam = ingredientFactory.CreateClam();
      }
  }
</code></pre>
</li>
<li>
<p>比萨店</p>
<pre><code>  public abstract class PizzaStore
  {
      //这里定义一个工厂方法
      abstract Pizza createPizza(string item);
      public Pizza orderPizza(string type) 
      {
          Pizza pizza = createPizza(type);
          print(&quot;--- Making a &quot; + pizza.getName() + &quot; ---&quot;);
          pizza.prepare();
          pizza.bake();
          pizza.cut();
          pizza.box();
          return pizza;
      }
  }

  public class NYPizzaStore : PizzaStore
  {
      protected Pizza CreatePizza(string name){
          Pizza pizza = null;
          PizzaIngredientFactory ingredientFactory = new PizzaIngredientFactory();

          if(name.Equals(&quot;cheese&quot;)){
              pizza = new CheesePizza(ingredientFactory);
              pizza.SetName(&quot;New York Style Cheese Pizza&quot;);
          }
          else if(name.Equals(&quot;clam&quot;)){
              pizza = new ClamPizza(ingredientFactory);
              pizza.SetName(&quot;New York Style Clam Pizza&quot;);
          }
          ...
      }
  }</code></pre>
</li>
</ul>
</div>
                    <div class="post_footer">
                        
                        <div class="meta">
                            <div class="info">
                                <span class="field tags">
                                    <i class="ri-stack-line"></i>
                                    
                                    <a href="https://lenzan.github.io/tags/%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/">工厂模式</a>
                                    
                                    <a href="https://lenzan.github.io/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/">设计模式</a>
                                    
                                </span>
                            </div>
                        </div>
                        
                    </div>
                </div>
                
                
            </div>
        </div>
    </div>
    <a id="back_to_top" href="#" class="back_to_top"><span>△</span></a>
    <footer class="footer">
    <div class="powered_by">
        <a href="https://varkai.com">Designed by VarKai,</a>
        <a href="http://www.gohugo.io/">Proudly published with Hugo</a>
    </div>

    <div class="footer_slogan">
        <span></span>
    </div>
</footer>
    <script src="https://lenzan.github.io/js/jquery-3.5.1.min.js"></script>
<link href="https://lenzan.github.io/css/fancybox.min.css" rel="stylesheet">
<script src="https://lenzan.github.io/js/fancybox.min.js"></script>
<script src="https://lenzan.github.io/js/zozo.js"></script>






</body>

</html>